﻿using System;
using System.Diagnostics;
using ChatRoom.Protocol;
using TingSLsocket;

namespace ChatRoom.Web.Server
{
    public interface IServer
    {
        void Forward(Guid srcId, byte[] buffer);
    }

    public sealed class ChatProxy : IDisposable
    {
        // ---------------------------------------- //
        #region "member fields"

        private readonly IServer _server;
        private readonly ClientInfo _clientInfo;
        private readonly CommandParser _cmdparser;
        private readonly CommandSerializer _serializer;

        #endregion

        // ---------------------------------------- //
        #region "constructor and destructor"

        public ChatProxy(ClientInfo clientInfo, IServer server)
        {
            _clientInfo = clientInfo;
            _server = server;

            _cmdparser = new CommandParser();
            _cmdparser.CmdParsedEvt += OnCmdParsedout;
            _cmdparser.ParsingException += (sender, args) => { throw args.Argument; };
            _cmdparser.Start();

            _serializer = new CommandSerializer();
        }

        public void Dispose()
        {
            _cmdparser.Dispose();
        }

        #endregion

        // ---------------------------------------- //
        #region "public API"

        public ClientInfo ClientInfo
        {
            get { return _clientInfo; }
        }

        public void Receive(byte[] buffer, int offset, int size)
        {
            _cmdparser.Write(buffer, offset, size);
        }

        #endregion

        // ---------------------------------------- //
        #region "private helpers"

        private void OnCmdParsedout(object sender, Tuple<int, byte[], int, int> args)
        {
            Debug.Assert(args.Item1 == Constants.CmdSendChat);
            ChatMessage msg = (ChatMessage)_serializer.Deserialize(args.Item2, args.Item3, args.Item4);
            msg.ClientId = _clientInfo.Id;

            byte[] buffer = _serializer.Serialize(Constants.CmdRecvChat, msg);
            _server.Forward(_clientInfo.Id, buffer);
        }

        #endregion
    }
}